#ifndef RECTMESH_HPP
#define RECTMESH_HPP

#include "structMeshBase.hpp"
#include "rectEdge.hpp"
#include "rectEdges.hpp"
#include "rectCell.hpp"
#include "rectCells.hpp"

namespace hms {

template<>
class MeshTraits<RectMesh>
{
public:
	using VertexType = Vector2s;
	using EdgeType   = RectEdge;
	using EdgesType  = RectEdges;
	using CellType   = RectCell;
	using CellsType  = RectCells;
	using SizeType   = Array2i;
};

class RectMesh : public StructMeshBase<RectMesh>
{
public:
	using Traits = MeshTraits<RectMesh>;

private:
	ArrayXs m_xCoords;
	ArrayXs m_yCoords;

	ArrayXs m_dx;
	ArrayXs m_dy;
	
public:
	RectMesh() = default;
	RectMesh(
		ArrayXs&& xCoords,
		ArrayXs&& yCoords,
		bool ghostsIncluded = false
	);

	auto xCoords() const -> const ArrayXs&;
	auto yCoords() const -> const ArrayXs&;

	auto xCoordsInner() const -> Eigen::VectorBlock<const ArrayXs>;
	auto yCoordsInner() const -> Eigen::VectorBlock<const ArrayXs>;

	auto dx() const -> const ArrayXs&;
	auto dy() const -> const ArrayXs&;

	auto dxInner() const -> Eigen::VectorBlock<const ArrayXs>;
	auto dyInner() const -> Eigen::VectorBlock<const ArrayXs>;

private:
	auto nCellsXImp() const -> Index;
	auto nCellsYImp() const -> Index;

	auto sizeImp() const -> SizeType;

	auto vertexImp(Index) const -> Vector2s;

	auto domainAreaImp() const -> scalar;

	void storeDiffs();

	friend MeshBase;
	friend StructMeshBase;
};

}

#endif